package com.n5x.controller;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.n5x.common.base.JsonModel;
import com.n5x.common.base.ResponseCode;
import com.n5x.common.base.TokenModel;
import com.n5x.common.sms.SmsUtils;
import com.n5x.common.system.Base64;
import com.n5x.common.util.StringUtil;
import com.n5x.common.weixinutils.*;
import com.n5x.model.admin.AdminUser;
import com.n5x.model.user.UserAccount;
import com.n5x.model.user.UserInfo;
import com.n5x.service.IAdminService;
import com.n5x.service.IUserService;
import com.n5x.service.RedisCacheUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户登陆接口方法Controller
 */
@Controller
//@CrossOrigin( maxAge = 3600)//配置这里就行了
public class LoginController extends BaseController {

    @InitBinder("userInfo")
    public void initBinderUserInfo(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("userInfo.");
    }

    @Autowired
    private IUserService iUserService;
    @Autowired
    private IAdminService iAdminService;

    /**
     * 前台普通注册
     *
     * @param login 登陆名称(如：手机号码)
     * @param pwd   登陆密码
     * @return JsonModel对象
     */
    @ResponseBody
    @RequestMapping(value = "/register", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel register(@RequestParam(value = "login", required = false) String login,
                              @RequestParam(value = "pwd", required = false) String pwd
    ) {
        logger.info("[用户注册]login:{},userInfo:{}", login, login);
        UserAccount.AccountType accountType = UserAccount.AccountType.手机号码;
        try {
            String code = request.getParameter("code");
            String token = request.getParameter("token");
            String address = request.getParameter("address") == null ? "" : request.getParameter("address");
            if (StringUtils.isBlank(login) || StringUtils.isBlank(pwd)) {
                return getResultError(ResponseCode.Common_Fail, "手机号或密码不能为空");
            }
            String serverCode = redisCache.getCacheObject(token);
            boolean codeCheck = false;
            if (null != serverCode) codeCheck = code.equals(serverCode);
            if (StringUtil.isBlank(code) || serverCode == null || !codeCheck) {
                return getResultError(ResponseCode.Common_Fail, "验证码错误");
            }
            boolean flag = iUserService.cheackUserByAccount(UserAccount.AccountType.手机号码, login);
            if (flag) {
                return getResultError(ResponseCode.Common_Fail, "已存在绑定账号");
            }
            UserInfo userInfo = new UserInfo();
            UserAccount account = new UserAccount().setLoginName(login).setPassword(pwd).setType(accountType.name());
            String ip = super.getIpAddr(request);
            //账号名就是手机号
            userInfo.setName(login);
            userInfo.setPhone(login);
            userInfo.setAddress(address);
            userInfo.setLastLoginIp(ip).setLastLoginTime(new Date());
            userInfo.setId(null); //保证为新创建账号信息
            //推荐人
            String recommend = request.getParameter("recommend");
            if (StringUtils.isNotBlank(recommend)) {
                userInfo.createRecommend(recommend);
            }
            userInfo = iUserService.saveUserInfoAndAccount(userInfo, account);
            String tokenClient = createLoginToken(userInfo.getId(), -1);
            return getResult(ResponseCode.Common_Success, tokenClient);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return getResultError(ResponseCode.Common_Error, e.getMessage());
        }
    }

    /**
     * 第三方登陆
     *
     * @param login OPEN_ID
     * @param type  账号类型下标
     * @return JsonModel对象
     */
    @ResponseBody
    @RequestMapping(value = "/thirdPartyRegister", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel thirdPartyRegister(
            @RequestParam(value = "login", required = false) String login,
            @RequestParam(value = "pwd", required = false) String pwd,
            @RequestParam(value = "openId", required = false) String openId,
            @RequestParam(value = "type", required = false) String type, HttpServletRequest request) {
        try {
            String code = request.getParameter("code");
            String codeToken = request.getParameter("token");
            String address = request.getParameter("address") == null ? "" : request.getParameter("address");
            logger.info("[第三方用户登陆]login:{},type:{}", login, type);

            if (StringUtils.isBlank(login)) {
                return getResultError(ResponseCode.Common_ParamError, "手机号不能为空");
            }
            if (StringUtils.isBlank(openId)) {
                return getResultError(ResponseCode.Common_ParamError, "openid为空");
            }
            //默认是微信登录
            if (StringUtils.isBlank(type)) {
                UserAccount.AccountType userType = UserAccount.AccountType.微信登陆;
            }

            UserInfo userInfo = iUserService.findUserInfoByLogin(login);

            if (userInfo == null) {
                //未绑定用户需要验证短信验证码
                String serverCode = redisCache.getCacheObject(codeToken);
                boolean codeCheck = false;
                if (null != serverCode) codeCheck = code.equals(serverCode);
                if (StringUtil.isBlank(code) || serverCode == null || !codeCheck) {
                    return getResultError(ResponseCode.Common_Fail, "验证码错误");
                }

                userInfo = new UserInfo();
                //未注册手机号码
                if (StringUtils.isBlank(pwd)) {
                    return getResultError(ResponseCode.Common_ParamError, "密码不能为空");
                }
                UserAccount account = new UserAccount().setLoginName(login).setPassword(pwd).setType(UserAccount.AccountType.手机号码.name());

                String ip = super.getIpAddr(request);
                //账号名就是手机号
                userInfo.setName(login);
                userInfo.setPhone(login);
                userInfo.setAddress(address);
                userInfo.setLastLoginIp(ip).setLastLoginTime(new Date());
                userInfo.setId(null); //保证为新创建账号信息
                //推荐人
                String recommend = request.getParameter("recommend");
                if (StringUtils.isNotBlank(recommend)) {
                    userInfo.createRecommend(recommend);
                }
                //新建账号保存手机账号
                userInfo = iUserService.saveUserInfoAndAccount(userInfo, account);
            }
            //已注册手机号码
            //保存微信账号
            UserAccount accountWeiXin = new UserAccount().setLoginName(openId).
                    setType(UserAccount.AccountType.微信登陆.name());
            accountWeiXin.setFkUserId(userInfo.getId());

            iUserService.saveUserAccount(accountWeiXin);
            String token = createLoginToken(userInfo.getId(), -1);
            return getResult(ResponseCode.Common_Success, token);
        } catch (Exception e) {
            e.printStackTrace();
            return getResultError(ResponseCode.Common_Error, e.getMessage());
        }
    }

    /**
     * 用户手机登陆
     *
     * @param login   登陆名称(如：手机号码)
     * @param pwd     登陆密码
     * @param request Http请求
     * @return JsonModel对象
     */
    @ResponseBody
    @RequestMapping(value = "/login")
    public JsonModel login(@RequestParam(value = "login", required = false) String login, @RequestParam(value = "pwd", required = false) String pwd, HttpServletRequest request) {
        try {
            logger.info("[用户登陆]login:{}", login);
            if (StringUtils.isBlank(login) || StringUtils.isBlank(pwd)) {
                return getResult(ResponseCode.Common_ParamError, "登陆名或登陆密码不能为空");
            }
            UserInfo userInfo = iUserService.findUserByAccount(UserAccount.AccountType.手机号码, login, pwd);
            if (userInfo == null) {
                return getResultError(ResponseCode.Common_DataNotFound, "登陆失败");
            }
            String ip = super.getIpAddr(request);
            userInfo.setLastLoginIp(ip).setLastLoginTime(new Date());
            String token = createLoginToken(userInfo.getId(), -1);
            iUserService.saveUserInfo(userInfo);
            return getResult(ResponseCode.Common_Success, token);
        } catch (Exception e) {
            e.printStackTrace();
            return getResultError(ResponseCode.Common_Error, e.getMessage());
        }
    }


    /**
     * 后台用户登陆
     *
     * @param login 登陆名称
     * @param pwd   密码
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/admin/login")
    public JsonModel adminLogin(@RequestParam(value = "login", required = false) String login,
                                @RequestParam(value = "pwd", required = false) String pwd) {
        logger.info("[后台用户登陆]login:{}", login);
        if (StringUtils.isBlank(login) || StringUtils.isBlank(pwd)) {
            return getResult(ResponseCode.Common_ParamError, "账号或密码不能为空");
        }
        AdminUser adminUser = iAdminService.cheackUserByAccount(login, pwd);
        if (adminUser == null) {
            return getResultError(ResponseCode.Common_DataNotFound, "登陆失败");
        }
        String token = createLoginToken(adminUser.getId(), -1);
        Map<String, Object> map = new HashMap<String, Object>();
        int index = AdminUser.Type.indexOf(adminUser.getType());
        if (index < 0) {
            return getResultError(ResponseCode.Common_DataNotFound, "用户类型出错");
        }
        map.put("fullName",adminUser.getFullName());
        map.put("type", index);
        map.put("token", token);
        return getResult(map);
    }


    public static final String TEST_USER_ID = "67498e50f21811e78b5600163e0adb3f";
    public static final String TEST_ADMIN_USER_ID = "1d718251d5fb11e78b5600163e0adb3f";

    //测试RedisCacheUtil
    @ResponseBody
    @RequestMapping(value = "/testToken", method = RequestMethod.GET)
    public JsonModel testRedis(String action, String userId, String token, UserInfo userInfo) {
        String ca = "";
        if (null != action && action.equals("user")) {
            if (null == userId) userId = TEST_USER_ID;
            ca = createLoginToken(userId, 60 * 60 * 24);
        } else if (action.equals("admin")) {
            if (null == userId) userId = TEST_ADMIN_USER_ID;
            ca = createLoginToken(userId, 60 * 60 * 24);
        } else {
            TokenModel tokenModel = getTokenModelByToken(token);
            ca = JSONObject.fromObject(tokenModel).toString();
        }
        return getResult(ca);
    }

    /**
     * 发送短信
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/sendSmsCode", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel sendSmsCode() {
        String phoneNum = request.getParameter("phoneNum");


        try {
            //空则电话号码不合法
            if (StringUtil.isBlank(phoneNum)) return getResultError(ResponseCode.Common_ParamError, "手机号不合法");


            String phoneReacord = redisCache.getCacheObject(phoneNum + "_sms");

            if (!StringUtil.isBlank(phoneReacord)) {
                return getResultError(ResponseCode.Common_Fail, "你的短信已经发送");
            }

            redisCache.setCacheObject(phoneNum + "_sms", phoneNum, 60);

            UserInfo userInfo = iUserService.findUserInfoByLogin(phoneNum);

            Map<String, String> keyMap = this.createSmsToken(-1);
            String code = keyMap.get("code");
            String token = keyMap.get("token");

            Map resMap = new HashMap();
            resMap.put("token", token);
            resMap.put("isRegister", userInfo == null ? 0 : 1);
            //非注册用户发送短信
            if (null == userInfo) SmsUtils.sendSmsCode(phoneNum, code);
            return getResult(resMap);
        } catch (Exception e) {
            return getResultError(ResponseCode.Common_Fail, "发送失败");
        }


    }

    /**
     * 重置密码
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/updateUserPwd", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel updateUserPwd() {
        String phoneNum = request.getParameter("phoneNum");
        String code = request.getParameter("code");
        String codeToken = request.getParameter("smsToken");
        String pwd = request.getParameter("pwd");

        try {
            //空则电话号码不合法
            if (StringUtil.isBlank(phoneNum)) return getResultError(ResponseCode.Common_ParamError, "手机号不合法");
            if (StringUtil.isBlank(pwd)) return getResultError(ResponseCode.Common_ParamError, "密码不能为空");
            //验证短信验证码
            String serverCode = redisCache.getCacheObject(codeToken);
            boolean codeCheck = false;
            if (null != serverCode) codeCheck = code.equals(serverCode);
            if (StringUtil.isBlank(code) || serverCode == null || !codeCheck) {
                return getResultError(ResponseCode.Common_Fail, "验证码错误");
            }

            UserAccount userAccount = iUserService.findAccountByName(UserAccount.AccountType.手机号码, phoneNum);
            if (null == userAccount) return getResultError(ResponseCode.Common_Fail, "该用户不存在!");
            userAccount.setPassword(pwd);
            String token = super.createLoginToken(userAccount.getFkUserId(), -1);
            String userAccountId = iUserService.saveUserAccount(userAccount);
            if (!StringUtil.isBlank(userAccountId)) return getResult(token);
            else return getResultError(ResponseCode.Common_Fail, "重置失败");
        } catch (Exception e) {
            return getResultError(ResponseCode.Common_Fail, "重置失败");
        }


    }


    /**
     * 发送短信
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/sendSmsCodeReset", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel sendSmsCodeReSet() {
        String phoneNum = request.getParameter("phoneNum");

        try {
            //空则电话号码不合法
            if (StringUtil.isBlank(phoneNum)) return getResultError(ResponseCode.Common_ParamError, "手机号不合法");


            String phoneReacord = redisCache.getCacheObject(phoneNum + "_sms");

            if (!StringUtil.isBlank(phoneReacord)) {
                return getResultError(ResponseCode.Common_Fail, "你的短信已经发送");
            }

            redisCache.setCacheObject(phoneNum + "_sms", phoneNum, 60);


            Map<String, String> keyMap = this.createSmsToken(-1);
            String code = keyMap.get("code");
            String token = keyMap.get("token");

            Map resMap = new HashMap();
            resMap.put("token", token);
            //非注册用户发送短信
            SmsUtils.sendSmsCode(phoneNum, code);
            return getResult(resMap);
        } catch (Exception e) {
            return getResultError(ResponseCode.Common_Fail, "发送失败");
        }


    }

    /**
     * 微信登录路由控制
     *
     * @return
     */
    @RequestMapping(value = "/auth", method = {RequestMethod.POST, RequestMethod.GET})
    public String auth() {
        String code = request.getParameter("code");
        String stateList = request.getParameter("state");
        String state = "";
        String[] paramList = stateList.split("ccb717");

        if (StringUtil.isBlank(paramList)) return "";
        Map<String, String> resMap = new HashMap();
        WeixinToken weiXinToken = CommonUtil.getUserInfoAccessToken(code);//通过这个code获取access_token
        String openId = weiXinToken.getOpenId();

        String url = "";
        String returnUrl = paramList[0];
        url = request.getScheme() + "://" + request.getServerName() + "/n5x_view/" + returnUrl + ".html";
        if (paramList.length >= 2) {
            state = paramList[1];
        }
        if (StringUtils.isNotEmpty(openId)) {
            logger.info("获取用户openid. [openid={}]", openId);


            if (url.contains("/n5xproject")) {
                url.replace("/n5xproject", "");
            }
            logger.info("获取用户路由openUrl. [openUrl={}]", url);

            //如果是验证注册
            if ("authrouter".equals(returnUrl)) {
                boolean isWeixin = iUserService.cheackUserByAccount(UserAccount.AccountType.微信登陆, openId);
                if (isWeixin) {
                    UserInfo user = iUserService.findUserInfoByLogin(openId);
                    if (user == null) getResultError("登录错误");

                    String token = createLoginToken(user.getId(), -1);
                    logger.info("获取用户路由openUrl. [openUrlToken={}]", url);
                    return "redirect:" + url + "?type=0&token=" + token + "&state=" + state;
                } else {
                    //查询
                    logger.info("获取用户路由openUrl. [openUrlopenId={}]", url);
                    return "redirect:" + url + "?type=1&openId=" + openId + "&state=" + state;
                }
            } else {
                return "redirect:" + url + "?openId=" + openId + "&state=" + state;
            }

        }
        return "redirect:" + url;
    }

    /**
     * 微信获取jsapi信息
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getTicketSign", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel getTicketSign() {
        JsonModel  jsonModel=null;
        try {
            WeixinToken acess_token = CommonUtil.getToken();//通过这个code获取access_token


            String nonce_str = WxPayUtil.getNonceStr().toUpperCase();//随机
            String timestamp=String.valueOf((System.currentTimeMillis() / 1000));//1970年到现在的秒数
            String ticket ="";
            if(null==redisCache.getCacheObject("jsTicket")){
                String accTokenStr = acess_token.getAccessToken();
                logger.info("acctoken:{}",accTokenStr);
                ticket = CommonUtil.getJsapi_ticket(accTokenStr);
                redisCache.setCacheObject("jsTicket", ticket, 7150);
            }else{
                ticket=redisCache.getCacheObject("jsTicket");
            }

            String url = request.getParameter("url");
            if(StringUtil.isBlank(url)) return  getResultError(ResponseCode.Common_ParamError,"url不能为空");
            url =  Base64.decode(url, "utf-8");

            String sign = "jsapi_ticket=" + ticket +
                    "&noncestr=" + nonce_str +
                    "&timestamp=" + timestamp +
                    "&url=" + url ;

            String signature = SHA1.encode(sign);
            Map res = new HashMap();
            res.put("timestamp",timestamp);
            res.put("noncestr",nonce_str);
            res.put("signature",signature);


            return  getResult(res);
        }catch (Exception e){
            logger.info("获取Ticket失败:{}",e.getMessage());
            return getResultError(e.getMessage());
        }

    }

    @ResponseBody
    @RequestMapping(value = "/getTokenByPhone", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonModel getTokenByPhone() {
        String phoneNum = request.getParameter("phoneNum");

        if (StringUtil.isBlank(phoneNum)) {
            return getResultError(ResponseCode.Common_ParamError, "手机号错误");
        }
        UserInfo userInfo = iUserService.findUserInfoByLogin(phoneNum);
        if (null == userInfo) {
            return getResultError(ResponseCode.Common_Error, "不存在此用户");
        }
        String token = super.createLoginToken(userInfo.getId(), 30 * 60);
        return getResult(token);
    }

    //获取前端发出的post请求
    @RequestMapping(value = "testpost", method = RequestMethod.POST)
    public String postjson(String param) throws Exception {

        Gson gs = new Gson();

        String userListStr = request.getParameter("userList");
        String token = request.getParameter("token");
        String userOne = request.getParameter("userInfo");

        List<UserInfo> jsonListObject = gs.fromJson(userListStr, new TypeToken<List<UserInfo>>() {
        }.getType());//把JSON格式的字符串转为List
        UserInfo userOneInfo = gs.fromJson(userOne, UserInfo.class);
/*        for (UserInfo userInfo :userInfos
             ) {
            System.out.println("id:"+userInfo.getId());
            System.out.println("name:"+userInfo.getName());
        }*/

        return "ok";
    }
}